package com.simple.study.base.service;

import com.github.pagehelper.PageInfo;
import com.simple.study.base.pojo.Base;
import com.simple.study.exception.BusinessException;
import tk.mybatis.mapper.entity.Example;

import java.util.List;

public interface BaseService<T extends Base, PK extends java.io.Serializable> {

    /**
     * <p>插入一条数据</p>
     * <p>支持Oracle序列,UUID,类似Mysql的INDENTITY自动增长(自动回写)</p>
     * <p>优先使用传入的参数值,参数值空时,才会使用序列、UUID,自动增长</p>
     *
     * @param entity 实体对象
     * @return int 受影响的行
     * @throws BusinessException
     */
    int insert(T entity) throws BusinessException;

    /**
     * <p>插入一条数据,只插入不为null的字段,不会影响有默认值的字段</p>
     * <p>支持Oracle序列,UUID,类似Mysql的INDENTITY自动增长(自动回写)</p>
     * <p>优先使用传入的参数值,参数值空时,才会使用序列、UUID,自动增长</p>
     *
     * @param entity 实体对象
     * @return int 受影响的行
     * @throws BusinessException
     */
    int insertSelective(T entity) throws BusinessException;

    /**
     * <p>保存或者更新，根据传入id主键是不是null来确认</p>
     *
     * @param entity 实体对象
     * @return int 受影响的行
     * @throws BusinessException
     */
    int save(T entity) throws BusinessException;

    /**
     * 根据主键删除实体
     *
     * @param key 主键
     * @return int 受影响的行
     * @throws BusinessException
     */
    int delete(PK key) throws BusinessException;

    /**
     * <p>根据条件删除数据</p>
     *
     * @param example 参数信息，类型可以为tk.mybatis.mapper.entity.Example
     * @return int 受影响的行
     * @throws BusinessException
     */
    int deleteByExample(Object example) throws BusinessException;

    /**
     * <p>根据实体类不为null的字段进行查询,条件全部使用=号and条件</p>
     *
     * @param entity 实体对象
     * @return int 受影响的行
     * @throws BusinessException
     */
    int delete(T entity) throws BusinessException;

    /**
     * <p>通过主键进行删除,这里最多只会删除一条数据</p>
     * <p>单个字段做主键时,可以直接写主键的值</p>
     * <p>联合主键时,key可以是实体类,也可以是Map</p>
     *
     * @param key 主键
     * @return int 受影响的行
     * @throws BusinessException
     */
    int deleteByPrimaryKey(PK key) throws BusinessException;

    /**
     * <p>根据主键进行更新, 最多只会更新一条数据</p>
     *
     * @param entity 实体对象 全更新，不允许出现null
     * @return int 受影响的行
     * @throws BusinessException
     */
    int updateByPrimaryKey(T entity) throws BusinessException;

    /**
     * <p>根据主键进行更新，只会更新不是null的数据</p>
     *
     * @param entity 目标对象
     * @return int 受影响的行
     * @throws BusinessException
     */
    int updateByPrimaryKeySelective(T entity) throws BusinessException;

    /**
     * 更新实体信息，以传入的实体对象的主键字段为条件
     *
     * @param entity 实体对象
     * @return int 受影响的行
     * @throws BusinessException
     */
    int updateAll(T entity) throws BusinessException;

    /**
     * <p>根据主键进行更新，只会更新不是null的数据</p>
     *
     * @param entity 实体对象
     * @return int 受影响的行
     * @throws BusinessException
     */
    int updateNotNull(T entity) throws BusinessException;

    /**
     * 根据Example及实体信息更新数据
     *
     * @param example 参数信息，类型可以为tk.mybatis.mapper.entity.Example
     * @param entity  实体对象
     * @return int 受影响的行
     * @throws BusinessException
     */
    int updateByExample(Example example, T entity) throws BusinessException;

    /**
     * <p>根据实体类不为null的字段查询总数,条件全部使用=号and条件</p>
     *
     * @param entity 实体对象
     * @return int 记录数
     * @throws BusinessException
     */
    int selectCount(T entity) throws BusinessException;

    /**
     * <p>返回满足条件的记录数</p>
     *
     * @param example 参数信息，类型可以为tk.mybatis.mapper.entity.Example
     * @return int 记录数
     * @throws BusinessException
     */
    int selectCountByExample(Example example) throws BusinessException;

    /**
     * <p>根据实体类不为null的字段进行查询,条件全部使用=号and条件</p>
     *
     * @param entity 实体对象
     * @return List<T> 结果集
     * @throws BusinessException
     */
    List<T> select(T entity) throws BusinessException;

    /**
     * <p>根据主键进行查询,必须保证结果唯一单个字段做主键时,可以直接写主键的值联合主键时,key可以是实体类,也可以是Map</p>
     *
     * @param key 主键
     * @return T 结果
     * @throws BusinessException
     */
    T selectByPrimaryKey(PK key) throws BusinessException;

    /**
     * 根据条件分页查询（与entity属性值相等的记录会被筛选出来）
     *
     * @param pageNum  当前页
     * @param pageSize 每页记录数
     * @param entity   实体对象
     * @return PageInfo 分页对象
     * @throws BusinessException
     */
    PageInfo<T> selectPage(int pageNum, int pageSize, T entity) throws BusinessException;

    /**
     * 根据条件分页查询（与entity属性值相等的记录会被筛选出来）
     * @param entity   实体对象
     * @return PageInfo 分页对象
     * @throws BusinessException
     */
    PageInfo<T> selectPage(T entity) throws BusinessException;


    /**
     * <p>根据条件分页查询（与entity属性值相等的记录会被筛选出来）</p>
     *
     * @param pageNum     当前页
     * @param pageSize    每页记录数
     * @param entity      对象
     * @param orderSqlStr (如:id desc)
     * @return PageInfo 分页对象
     * @throws BusinessException
     */
    PageInfo<T> selectPage(int pageNum, int pageSize, T entity, String orderSqlStr) throws BusinessException;

    /**
     * <p>根据实体类不为null的字段进行查询,条件全部使用=号and条件</p>
     *
     * @param entity 实体对象
     * @return T 结果
     * @throws BusinessException
     */
    T selectOne(T entity) throws BusinessException;

    /**
     * <p>根据主键查询实体</p>
     *
     * @param key 主键
     * @return T 结果
     * @throws BusinessException
     */
    T selectByKey(PK key) throws BusinessException;

    /**
     * <p>根据条件查询数据，返回符合条件的数据集合，不分页</p>
     *
     * @param example 参数信息，类型可以为tk.mybatis.mapper.entity.Example
     * @return List<T> 结果集
     * @throws BusinessException
     */
    List<T> selectByExample(Example example) throws BusinessException;

    /**
     * <p>查询所有记录，不使用条件过滤，不分页</p>
     *
     * @return List<T> 结果集
     * @throws BusinessException
     */
    List<T> selectAllEntities() throws BusinessException;

    /**
     * <p>根据条件查询数据并分页</p>
     *
     * @param example  参数信息，类型可以为tk.mybatis.mapper.entity.Example
     * @param pageNum  当前页
     * @param pageSize 每页记录数
     * @return PageInfo<T> 分页对象
     * @throws BusinessException
     */
    PageInfo<T> selectPagingByExample(Object example, int pageNum, int pageSize) throws BusinessException;

}
